# 请使用已学习的装饰器相关知识自己实现 functools.lru_cache。

import functools


def lru_cache(maxsize=128):
    def decorator(func):
        cache = {}  # 用于保存缓存的字典
        keys = []  # 用于记录键的顺序，以实现最近最少使用

        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            key = args + tuple(kwargs.items())

            # 如果结果已经在缓存中，直接返回缓存的结果
            if key in cache:
                # 更新键的顺序
                keys.remove(key)
                keys.append(key)
                return cache[key]

            # 如果缓存已满，删除最早的键
            if len(keys) >= maxsize:
                oldest_key = keys.pop(0)
                del cache[oldest_key]

            # 计算结果并保存到缓存中
            result = func(*args, **kwargs)
            cache[key] = result
            keys.append(key)

            return result

        return wrapper

    return decorator


# 使用 lru_cache 装饰器
@lru_cache(maxsize=2)
def expensive_function(n):
    print(f"Calculating result for {n}")
    return n * 2


# 测试
print(expensive_function(2))  # 计算结果并缓存
print(expensive_function(3))  # 计算结果并缓存
print(expensive_function(2))  # 直接从缓存中获取
print(expensive_function(4))  # 计算结果并缓存，此时缓存已满，将删除最早的结果
print(expensive_function(3))  # 计算结果并缓存，由于 3 是最近使用的，因此不会删除
